import os, time, socket, sys

def ChangeToPath(path):
    try:
        os.chdir(path)
    except:
        print('Error changing to Path %s' % path)
        
def FileSize(path):
    size = 0
    try: 
        size = os.path.getsize(path)
        return size
    except:
        return 0
    
def FileSizeConvertor(num):
    for x in ['bytes','KB','MB','GB']:
        if num < 1024.0 and num > -1024.0:
            return "%3.1f%s" % (num, x)
        num /= 1024.0
    return "%3.1f%s" % (num, 'TB')
                
class GroupFolderLevel(object):
    """
        PATH = el path donde empezamos si por ejemplo
        dir mis documentos
            -Documentos <- Path
            -VMs
            -Musica
            
        FolderDepth - Cuantos niveles abajo de este folder vamos a llegar.
    """
    def __init__(self, GFolder, FolderLevel, FilesLiving, dirs):
        self.CurrentPath= GFolder
        self.FolderLevel = FolderLevel
        self.filesLiving = FilesLiving
        self.dirsLiving = dirs

class RootFilesystem(object):
    def __init__(self, RootPath):
        self.RootPath = RootPath
        self.TotalSize = 0
        self.NumOfFiles = None
        self.NumOfFolders = None
        
    def TotalSizeTree(self, size):
        self.TotalSize += size 
            
class Crawler(RootFilesystem):
    def __init__(self, RootPath, MaxDepth):
        RootFilesystem.__init__(self, RootPath)
        self.LevelFilesyste = {}
        self.Level = 0
        self.MaxDepth = MaxDepth
        self.LoggingError = []
        
    def AddOneLevel(self):
        self.Level = self.Level + 1
        
    def WalkingDirs(self, path):
        dirs = []
        files = []
        print('Path: ', path) #Remover
        try:
            for root, dirs, files in os.walk(path):
                    break
        except:
            self.LoggingError.append("Error al caminar por los archivos")
        print('dirs %s files %s' % (dirs, files)) #Remover
        return dirs, files 


class CrawlerTxtCreator(Crawler):
    def __init__(self, RootPath, MaxDepth):
        Crawler.__init__(self, RootPath, MaxDepth)
        self.cl ={}
        self.FileTree = None
    
    def CreateFileHeader(self):
        buf =  '#'*20
        buf += """
\t %s 
\t %s 
\t %s
\t FileName %s\n""" % ((time.asctime(time.localtime())), sys.platform, socket.gethostname(),self.WorkingFolder)
        buf += '#'*20
        return buf
    
    def OpenFile(self, **fileopts):
        try:
            self.FileTree = open(**fileopts)
        except:
            print("Error en OpenFile")
    
    def FileWriting(self, buff):
        self.FileTree.write(buff + '\n')
    
    def CreateWorkingFolder(self, FolderName = 'Tmp', AppendExtra = None):
        self.WorkingFolder = AppendExtra + FolderName
        try:
            os.makedirs(self.WorkingFolder, exist_ok = True)
        except:
            raise RuntimeError('Imposible crear archivo para copia de archivos')
        
          
    def WriteFilesysteOnTxt_orig(self, FileName, CurrentPath):
        """
            Escribimos en un archivo de texto todo el filesystem al que hacemos el crawling
        """
        CPath = [CurrentPath]
        print('zzzz', CurrentPath)
        FileParms = dict(file=self.WorkingFolder+ '\\' + FileName, mode='wt', errors= 'replace')
        ff = self.OpenFile(**FileParms)
        assert self.WorkingFolder is not None, 'Es necesario Definir un Folder de trabajo a traves de la funcion CreateWorkingFolder'
        header = self.CreateFileHeader()
        self.FileWriting(header)
        for i in range(self.Level, self.MaxDepth): ## ACA SE REPITE a junto con el for de abajo cambiarlo
            print('Self.Level', self.Level)
            self.FileWriting("###============%d===========####\n" % (self.Level))
            self.cl[self.Level] = []
            NewPath = []
            for a in range(len(CPath)):
                print("CPath[a]", CPath[a])
                dirs, files = self.WalkingDirs(CPath[a])
                print(dirs)
                self.cl[self.Level].append(GroupFolderLevel(CPath[a], self.Level, files, dirs)) #esto no tiene que sobre escribir si no agregar a la lista
                if self.Level == 0 and len(dirs) == 0:
                    if len(dirs) != 0:
                        #ANALIZAMOS LOS ARCHIVOS SI ES QUE EXISTEN AUNQUE NO TENGAMOS DIRECTORIOS
                        pass
                    print('Nada que hacer')
                  #  sys.exit()
                for b in dirs:
                    NewPath.append("%s\%s" % (self.cl[self.Level][a].CurrentPath, b))
                for c in files:
                    cpath = "%s\%s" % (CPath[a],c) 
                    size = FileSize(cpath)
                    print('Size: ', size)
                    self.TotalSizeTree(size) #Descomentar
                    self.FileWriting(cpath + "  -- [%s]" % (FileSizeConvertor(size)))
            CPath = NewPath
            self.AddOneLevel()
        print("Gran Total", self.TotalSize)
        print("Working folder", self.WorkingFolder)
        self.FileWriting("\n###Gran Total [%s][%d]###\n\n" % (FileSizeConvertor(self.TotalSize), self.TotalSize))
        
    def WriteFilesysteOnTxt(self, FileName, CurrentPath):
        """
            Escribimos en un archivo de texto todo el filesystem al que hacemos el crawling
        """
        CPath = [CurrentPath]
        print('zzzz', CurrentPath)
        FileParms = dict(file=self.WorkingFolder+ '\\' + FileName, mode='wt', errors= 'replace')
        ff = self.OpenFile(**FileParms)
        assert self.WorkingFolder is not None, 'Es necesario Definir un Folder de trabajo a traves de la funcion CreateWorkingFolder'
        header = self.CreateFileHeader()
        self.FileWriting(header)
        for i in range(self.Level, self.MaxDepth): ## ACA SE REPITE a junto con el for de abajo cambiarlo
            print('Self.Level', self.Level)
            self.FileWriting("###============%d===========####\n" % (self.Level))
            self.cl[self.Level] = []
            NewPath = []
            for a in range(len(CPath)):
                print("CPath[a]", CPath[a])
                dirs, files = self.WalkingDirs(CPath[a])
                print(dirs)
                self.cl[self.Level].append(GroupFolderLevel(CPath[a], self.Level, files, dirs)) #esto no tiene que sobre escribir si no agregar a la lista
                if self.Level == 0 and len(dirs) == 0:
                    if len(dirs) != 0:
                        #ANALIZAMOS LOS ARCHIVOS SI ES QUE EXISTEN AUNQUE NO TENGAMOS DIRECTORIOS
                        pass
                    print('Nada que hacer')
                  #  sys.exit()
                for b in dirs:
                    NewPath.append("%s\%s" % (self.cl[self.Level][a].CurrentPath, b))
                for c in files:
                    cpath = "%s\%s" % (CPath[a],c) 
                    size = FileSize(cpath)
                    print('Size: ', size)
                    self.TotalSizeTree(size) #Descomentar
                    self.FileWriting(cpath + "  -- [%s]" % (FileSizeConvertor(size)))
            CPath = NewPath
            self.AddOneLevel()
        print("Gran Total", self.TotalSize)
        self.FileWriting("\n###Gran Total [%s][%d]###\n\n" % (FileSizeConvertor(self.TotalSize), self.TotalSize))
        
        